// i.d(t, { Vs: () => n, k3: () => TourData })
import tourStateEnum, { tourAniState } from "../enum/tourState.enum"
import { TourTransitionType } from "../enum/tourTransition.enum"
import Data from "../object/Data"
import HighlightReel, { ReelItem, ReelItemOverrides } from "../object/HighlightReel"
import Snapshot from "../object/Snapshot"
import Sweep from "../object/Sweep"

interface transitionConfig {
  active: boolean
  type: number
  promise: Promise<any>
  stop: () => Promise<any>
  toIndex: number
}

export default class TourData extends Data {
  snapshots: Record<string, Snapshot>
  activeReel: HighlightReel
  allowedModes: number[]
  modelSweeps: Sweep[]
  looping: boolean
  enabledTourStops: string[]
  tourPlaying: boolean
  tourEnded: boolean
  tourState: number
  tourCurrentSnapshot: number
  transition: transitionConfig
  tourCurrentSnapshotSid: string
  constructor(e: Record<string, Snapshot> = {}, t: HighlightReel, i: number[], s: Sweep[], r: boolean) {
    super()
    this.snapshots = e
    this.activeReel = t
    this.allowedModes = i
    this.modelSweeps = s
    this.looping = r
    this.name = "tour"
    this.enabledTourStops = []
    this.tourPlaying = !1
    this.tourEnded = !1
    this.updateEnabledStops(i)
    this.tourState = tourStateEnum.Inactive
    this.tourCurrentSnapshot = -1
    this.transition = {
      active: !1,
      type: TourTransitionType.Move,
      promise: Promise.resolve(),
      stop: () => Promise.resolve(),
      toIndex: -1
    }
    this.commit()
  }
  updateEnabledStops(e) {
    if (((this.enabledTourStops = []), this.activeReel && this.activeReel.reel))
      for (const t of this.activeReel.reel)
        if (t && t.sid in this.snapshots) {
          const i = this.snapshots[t.sid]
          const n = i.metadata.cameraMode
          const s = i.metadata.scanId
          const r = -1 !== e.indexOf(n)
          const o = this.modelSweeps.findIndex(e => e.id === s)
          const a = void 0 !== s && -1 !== o && this.modelSweeps[o].enabled
          const l = !s
          r && (l || a) && this.enabledTourStops.push(t.sid)
        }
  }
  addSnapshotToTour(e: Snapshot, t = tourAniState.Current) {
    this.snapshots[e.sid] = e
    this.allowedModes.includes(e.metadata.cameraMode) && this.enabledTourStops.push(e.sid)
    const i = this.tourCurrentSnapshotSid
    this.tourCurrentSnapshotSid = e.sid
    switch (t) {
      case tourAniState.Beginning:
        this.tourCurrentSnapshot = 0
        this.activeReel.reel.insert(0, { sid: e.sid })
        break
      case tourAniState.End:
        this.tourCurrentSnapshot = this.enabledTourStops.length - 1
        this.activeReel.reel.push({ sid: e.sid })
        break
      case tourAniState.Current:
        if (!i) {
          this.tourCurrentSnapshot = this.enabledTourStops.length - 1
          this.activeReel.reel.push({ sid: e.sid })
        } else {
          let t = this.activeReel.reel.findIndex(e => !!e && e.sid === i) + 1
          if (t <= 0 || t > this.activeReel.reel.length) {
            t = this.activeReel.reel.length - 1
          }
          this.tourCurrentSnapshot = this.tourCurrentSnapshot + 1
          this.activeReel.reel.insert(t, { sid: e.sid })
        }
        break
      default:
        throw new Error(`Tours.addSnapshotToTour not implemented: ${t}`)
    }
    this.commit()
  }
  clearHighlightOverrides(e: string, noTrans: boolean, noPan: boolean) {
    if (!noTrans && !noPan) return
    const n: Partial<ReelItemOverrides> = {}
    noTrans && (n.transitionType = void 0)
    noPan && ((n.panDirection = void 0), (n.panAngle = void 0))
    this.applyHighlightOverrides(e, n)
  }
  clearAllHighlightOverrides() {
    this.getReel().reel.forEach(e => {
      e && this.clearHighlightOverrides(e.sid, !0, !0)
    })
  }
  resetAllTransitionTypeOverrides() {
    if (this.activeReel && this.activeReel.reel) {
      let e = !1
      this.activeReel.reel.forEach((t, i) => {
        if (t?.overrides?.transitionType) {
          delete t.overrides.transitionType
          this.activeReel.reel.update(i, t)
          e = !0
        }
      })
      e && this.activeReel.setDirty()
    }
  }
  resetAllPanSettingOverrides() {
    if (this.activeReel && this.activeReel.reel) {
      let e = !1
      this.activeReel.reel.forEach((t, i) => {
        t &&
          t.overrides &&
          ((void 0 === t.overrides.panAngle && void 0 === t.overrides.panDirection) ||
            (delete t.overrides.panAngle, delete t.overrides.panDirection, (e = !0), this.activeReel.reel.update(i, t)))
      }),
        e && this.activeReel.setDirty()
    }
  }
  applyHighlightOverrides(sid: string, t: Partial<ReelItemOverrides>) {
    const i = this.activeReel.reel.findIndex(t => !!t && t.sid === sid)
    this.setHighlightOverrides(i, t)
  }
  setHighlightOverrides(e: number, t: Partial<ReelItemOverrides>) {
    const i = this.activeReel.reel.get(e)
    if (!i) throw Error(`Highlight not found for ${e}`)
    const n: Partial<ReelItem> = { sid: i.sid }
    i.overrides
      ? ((n.overrides = Object.assign({}, i.overrides)),
        t.hasOwnProperty("panDirection") && (n.overrides.panDirection = t.panDirection),
        t.hasOwnProperty("transitionType") && (n.overrides.transitionType = t.transitionType),
        t.hasOwnProperty("panAngle") && (n.overrides.panAngle = t.panAngle))
      : (n.overrides = {
          transitionType: t.transitionType,
          panDirection: t.panDirection,
          panAngle: t.panAngle
        }),
      this.activeReel.reel.update(e, n)
  }
  moveTourStop(e: string, t: string) {
    const from = this.activeReel.reel.findIndex(t => !!t && t.sid === e)
    const to = this.activeReel.reel.findIndex(e => !!e && e.sid === t)
    this.activeReel.reel.move(from, to)
  }
  clear() {
    this.resetEmptyReel()
    this.enabledTourStops.length = 0
    this.activeReel.reel.length = 0
    this.commit()
  }
  removeTourStop(e) {
    const t = this.enabledTourStops.indexOf(e)
    const i = this.activeReel.reel.findIndex(t => !!t && t.sid === e)
    const n = this.getTourIndexBySid(e)
    t > -1 && this.enabledTourStops.splice(t, 1)
    if (this.enabledTourStops.length > 0) {
      const e = n <= this.tourCurrentSnapshot ? this.tourCurrentSnapshot - 1 : this.tourCurrentSnapshot
      this.setTourCurrentSnapshotByIndex(Math.max(e, 0))
    } else this.resetEmptyReel()
    this.activeReel.reel.remove(i)
  }
  getReel() {
    return this.activeReel
  }
  isLooping() {
    return this.looping
  }
  isTourActive() {
    return this.tourState !== tourStateEnum.Inactive
  }
  getCurrentTourState() {
    return {
      currentStep: this.getTourCurrentSnapshotIndex(),
      tourPlaying: this.tourPlaying,
      totalSteps: this.getSnapshotCount(),
      tourEnded: this.tourEnded,
      activeStep: this.transition && -1 !== this.transition.toIndex ? this.transition.toIndex : this.getTourCurrentSnapshotIndex(),
      highlights: this.getReelHighlights(),
      transition: this.transition
    }
  }
  isTourTransitionActive() {
    return this.transition.active
  }
  getTourTransitionType() {
    return this.transition.type
  }
  useTransition(e: transitionConfig) {
    this.transition = e
    this.commit()
  }
  setTourTransitionToIndex(e: number) {
    this.transition.toIndex = e
    this.commit()
  }
  async stopTourTransition() {
    await this.transition.stop()
  }
  iterateSnapshots(e: (v: Snapshot, i: number) => void) {
    let t = 0
    this.activeReel.reel.forEach(i => {
      if (i && this.isEnabled(i.sid)) {
        const n = this.snapshots[i.sid]
        e(n, t++)
      }
    })
  }
  isSnapshotInTour(sid: string) {
    return -1 !== this.activeReel.reel.findIndex(t => !!t && t.sid === sid)
  }
  getEnabledSnapshots() {
    const e: Snapshot[] = []
    this.iterateSnapshots((t, i) => {
      e.push(t)
    })
    return e
  }
  updateSnapshots(e: Record<string, Snapshot>) {
    this.snapshots = e
  }
  async getPhotosForTour() {
    const e: {
      name: string
      sid: string
      thumbnailUrl: string
      inReel: boolean
      created: Date
    }[] = []
    for (const t in this.snapshots) {
      const i = this.snapshots[t]
      "tour" !== i.category &&
        "panorama" !== i.category &&
        e.push({
          name: i.name,
          sid: i.sid,
          thumbnailUrl: await i.thumbnailUrl.get(),
          inReel: -1 !== this.activeReel.reel.findIndex(e => !!e && e.sid === t),
          created: i.created
        })
    }
    e.sort((e, t) => t.created.getTime() - e.created.getTime())
    return e
  }
  getSnapshot(e: string) {
    return this.snapshots[e]
  }
  getHighlightDescription(sid: string) {
    const index = this.activeReel.reel.findIndex(t => !!t && t.sid === sid)
    const reelEntry = this.activeReel.reel.get(index)
    return { snapshot: this.getSnapshot(sid), reelEntry }
  }
  getReelHighlights() {
    const e: {
      sid: string
      snapshot: Snapshot
      panDirection: string
      panAngle: number
      transitionType: number
    }[] = []
    this.activeReel.reel.forEach(t => {
      if (t && this.isEnabled(t.sid)) {
        const i = this.snapshots[t.sid]
        e.push({
          sid: i.sid,
          snapshot: i,
          panDirection: t.overrides && t.overrides.panDirection,
          panAngle: t.overrides && t.overrides.panAngle,
          transitionType: t.overrides && t.overrides.transitionType
        })
      }
    })
    return e
  }
  getSnapshotCount() {
    return this.enabledTourStops.length
  }
  getTourState() {
    return this.tourState
  }
  setTourState(e: number) {
    this.tourState = e
    this.commit()
  }
  getTourCurrentSnapshotIndex() {
    return this.tourCurrentSnapshot
  }
  getTourCurrentSnapshotSid() {
    return this.tourCurrentSnapshotSid
  }
  getTourSnapshotSid(e: number) {
    let t = 0
    for (const i of this.activeReel.reel)
      if (i && this.isEnabled(i.sid)) {
        if (t === e) return i.sid
        t++
      }
    throw new Error("getTourSnapshotSid() -> Invalid snapshot index.")
  }
  getTourSnapshotsWithSweepId(e: string) {
    const t = []
    for (const i of this.activeReel.reel) i && i.sid in this.snapshots && this.snapshots[i.sid].metadata.scanId === e && t.push(i.sid)
    return t
  }
  setTourCurrentSnapshotByIndex(e: number) {
    if (e < 0 || e > this.getSnapshotCount()) throw new Error("setTourCurrentSnapshotByIndex() -> Invalid tour index.")
    let t = -1
    for (const i of this.activeReel.reel)
      if (i && this.isEnabled(i.sid) && (t++, t === e)) {
        ;(this.tourCurrentSnapshot = e), (this.tourCurrentSnapshotSid = i.sid)
        break
      }
    ;-1 === t && this.resetEmptyReel(), this.setTourTransitionToIndex(-1), this.commit()
  }
  getTourIndexBySid(e: string) {
    let t = -1
    for (const i of this.activeReel.reel) if (i && this.isEnabled(i.sid) && (t++, i.sid === e)) return t
    return -1
  }
  isEnabled(e: string) {
    return -1 !== this.enabledTourStops.indexOf(e)
  }
  resetEmptyReel() {
    this.tourCurrentSnapshot = -1
    this.tourCurrentSnapshotSid = void 0
    this.setTourTransitionToIndex(-1)
    this.commit()
  }
}
